<script lang="ts" setup>
// g6对象
import G6 from "@antv/g6";

// vue
import { onMounted, onUnmounted } from "vue";

// 组件
import Affix from "../Affix/index.vue"; // 右下角图钉操作栏
import DrawerRight from "../DrawerRight/index.vue"; // 右侧抽屉
import DrawerLeft from "../DrawerLeft/index.vue"; // 右侧抽屉
import relationDialog from "../relationDialog/index.vue"; // 关系拓展组件
import { ElMessage } from "element-plus";

// Store
import { useCanvasStoreHook } from "@/stores/modules/canvas"; // 画布
import { useSelectGraphStoreHook } from "@/stores/modules/selectGraph"; // 画布

// 方法
import { emitter } from "@/utils/mitt"; // 组件通讯
import file from "@/utils/export"; // 文件操作方法，dataURLtoBlob 将 base64 转换成 blob

// 接口
import { fetchCanvasStore, similarAnalysis } from "@/api/associationAnalysis"; // 保存画布

import { initGraph, returnNodeSize } from "./common/index";
import { uniqueFunc } from "@/utils/index";

import { isNeedStop } from "./common/menuEvent";

const useCanvasStore = useCanvasStoreHook(); // 画布
const useSelectGraphStore = useSelectGraphStoreHook(); // 画布

const relationDialogShow = ref(false); // 关系拓展弹窗显示与隐藏

// 画布实例对象
let graph = {
  value: null,
};

// 获取canvas数据，渲染画布
const initData = () => {
  let canvas = useCanvasStore.getCanvasByData(); // 当前打开的uuid中的 canvas数据
  const data = JSON.parse(JSON.stringify(canvas)); // 深拷贝，避免影响全局
  console.log(data, "initData");
  // graph.value.clear();
  G6.Util.processParallelEdges(data.edges, 25);
  // 在渲染和动画完成后调用
  // graph.value.fitCenter();

  // TODO: read 和 render 情况需要做判断处理。
  graph.value.read(data);

  // 已锁定的节点继续锁定
  canvas.nodes.forEach((item) => {
    if (item.isLock) {
      const node = graph.value.findById(item.id);
      node.lock();
    }
  });
};

// 获取dom需要在onMounted之后获取。并给graph赋值g6实例
onMounted(() => {
  initCanvans();
  initData();
});

const initCanvans = () => {
  const graph1 = initGraph();
  graph.value = graph1;
};

provide("graphModule", graph);

// Store中的canvas值进行监听，改变时重新获取值并渲染。
useCanvasStore.$subscribe(() => {
  console.log(isNeedStop.value, "isNeedStop");
  if (isNeedStop.value) return (isNeedStop.value = false); // 删除的时候不用更新数据
  console.log("监听到数据发生改变，重新渲染画布～");
  initData();
});

// 顶部操作栏保存按钮事件监听触发
emitter.on("handleSave", async () => {
  returnNodeSize(); // 将图中节点还原成初始大小（节点重要性分析时会改变节点大小）
  const data = {
    // 现在图中的所有节点
    nodes: graph.value.getNodes().map((item) => item.getModel()),
    edges: graph.value.getEdges().map((item) => item.getModel()),
  };
  // console.log(graph.value.getNodes(), graph.value.getEdges(), data);
  const dataURL = graph.value.toDataURL(); // 获取当前画布截图base64
  let formData = new FormData();
  formData.append("file", file.dataURLtoBlob(dataURL)); // base64 转换成 blob
  // TODO: data值后续需要修改为通过graph对象获取。
  formData.append("data", JSON.stringify(data));
  formData.append("name", useCanvasStore.getCanvasByName());
  formData.append("id", useCanvasStore.getCanvasById());
  let res = await fetchCanvasStore(formData);
  useCanvasStore.setCanvasId(useCanvasStore.active, res.data.id);
  useCanvasStore.setCanvas(JSON.parse(res.data.data));

  sessionStorage.removeItem("graphIsEdit"); // 标记是否有未保存的数据
  ElMessage({
    type: "success",
    message: "保存成功",
  });
});

// 顶部操作栏关系拓展触发
emitter.on("handleRelationshipExpansion", () => {
  relationDialogShow.value = true;
});

// 顶部操作栏导出图片
emitter.on("handleExportImage", () => {
  graph.value.downloadImage(
    useCanvasStore.getCanvasByName(),
    "image/png",
    "#ffffff"
  );
});

// 顶部操作栏导出数据
emitter.on("handleExportData", () => {
  let data = graph.value.save();
  const jsonString: string = JSON.stringify(data, null, 2);
  const blob: Blob = new Blob([jsonString], { type: "application/json" });
  const url: string = URL.createObjectURL(blob);
  const link: HTMLAnchorElement = document.createElement("a");
  link.href = url;
  link.download = `${useCanvasStore.getCanvasByName()}.json`;
  document.body.appendChild(link);
  link.click();
  document.body.removeChild(link);
});

// 顶部操作栏选择操作
emitter.on("handleSelect", (type) => {
  const types = ["drag-canvas", "brush-select", "lasso-select"];
  graph.value.removeBehaviors(types, "default");
  graph.value.addBehaviors(
    {
      type,
      trigger: "drag",
    },
    "default"
  );
});

// 顶部操作栏全选操作
emitter.on("handleAllSelect", () => {
  let nodes = graph.value.getNodes();
  let edges = graph.value.getEdges();
  let data = {
    nodes: [],
    edges: [],
  };
  nodes.forEach((item) => {
    graph.value.setItemState(item, "selected", true);
    data.nodes.push(item._cfg.model);
  });
  edges.forEach((item) => {
    graph.value.setItemState(item, "selected", true);
    data.edges.push(item._cfg.model);
  });
  useSelectGraphStore.setSelectCanvas(data);
});

// 顶部操作栏反选操作
emitter.on("handleInvert", () => {
  let nodes = graph.value.getNodes();
  let edges = graph.value.getEdges();
  let data = {
    nodes: [],
    edges: [],
  };
  nodes.forEach((item) => {
    let isSelect = item._cfg.states?.includes("selected");
    graph.value.setItemState(item, "selected", !isSelect);
    if (!isSelect) {
      data.nodes.push(item._cfg.model);
    }
  });
  edges.forEach((item) => {
    let isSelect = item._cfg.states?.includes("selected");
    graph.value.setItemState(item, "selected", !isSelect);
    if (!isSelect) {
      data.edges.push(item._cfg.model);
    }
  });
  if (data.nodes.length || data.edges.length) {
    useSelectGraphStore.setSelectCanvas(data);
  } else {
    useSelectGraphStore.setSelectCanvas(null);
  }
});

emitter.on("handleFiltersEdges", (list) => {
  let edges = graph.value.getEdges();
  list.forEach((item) => {
    edges.forEach((ele) => {
      if (item.code === ele._cfg.model.edgeName) {
        if (item.isCheck) {
          ele.show();
        } else {
          ele.hide();
        }
      }
    });
  });
});

emitter.on("handleFiltersNodes", (list) => {
  let nodes = graph.value.getNodes();
  let edges = graph.value.getEdges();
  // console.log(list, edges);

  // 将要要隐藏的放后面，以为要隐藏节点相关联的边
  let listData = JSON.parse(JSON.stringify(list)).sort((item) =>
    item.isCheck ? -1 : 1
  );
  listData.forEach((item) => {
    nodes.forEach((ele) => {
      if (item.code === ele._cfg.model.tageName) {
        if (item.isCheck) {
          ele.show();
        } else {
          ele.hide();
        }

        edges.forEach((it) => {
          if (
            it._cfg.model.source == ele._cfg.model.id ||
            it._cfg.model.target == ele._cfg.model.id
          ) {
            console.log(it._cfg.model, item.isCheck);
            if (item.isCheck) {
              it.show();
            } else {
              it.hide();
            }
          }
        });
      }
    });
  });
});
/**
 * 布局功能
 */
emitter.on("handleChangeLayout", (type) => {
  let cfg: any = {
    type,
    animate: true,
    preventOverlap: true,
    nodeSize: 40,
    nodeStrength: 5,
    linkDistance: 150,
    nodeSpacing: (d) => {
      // 防止重叠时节点边缘间距的最小值;
      // console.log(d, "d");
      if (d.label.length > 12) {
        return 70;
      }
      return 40;
    },
  };
  switch (type) {
    case "dagre":
      cfg = {
        type: "dagre",
        rankdir: "TB",
      };
      break;
    case "dagre-lr":
      cfg = {
        type: "dagre",
        rankdir: "LR",
      };
      break;
    case "grid":
      cfg = {
        type: "grid",
      };
      break;
    case "neural":
      cfg = {
        row: 3,
        type: "grid",
        sortBy: "tageName",
      };
      break;
    case "radial":
      cfg = {
        type: "radial",
        linkDistance: 300,
        strictRadial: true,
      };
      break;
  }
  graph.value.updateLayout(cfg);
  // 在渲染和动画完成后调用
  // graph.value.fitCenter();
  // setTimeout(() => {
  //   nextTick(() => {
  //     // graph.value.fitView(100);
  //   });
  // }, 500);
});

/**
 * 锁定解锁
 */
emitter.on("lockChangeEvent", (type) => {
  // let selectedNode = JSON.parse(
  //   JSON.stringify(useSelectGraphStore.getSelectCanvas())
  // );
  // console.log(selectedNode, useSelectGraphStore.getSelectCanvas(), type);
  if (type == "lock") {
    useSelectGraphStore.getSelectCanvas().nodes.forEach((item) => {
      const node = graph.value.findById(item.id);
      node.lock();

      let model = {
        isLock: true,
      };
      node.update(model);
    });

    // useSelectGraphStore.setLockSelectCanvas(
    //   // 将锁定的节点存起来，解锁时需要原始节点的样式
    //   selectedNode
    // );
  } else if (type == "unlock") {
    let arr = useSelectGraphStore.getSelectCanvas();
    arr.nodes.forEach((item) => {
      const node = graph.value.findById(item.id);
      node.unlock();

      let model = {
        isLock: false,
      };
      node.update(model);
    });
    // let lockArr = useSelectGraphStore.getLockSelectCanvas(); // 锁定的节点
    // arr.nodes.forEach((item) => {
    //   const node = graph.value.findById(item.id);
    //   node.unlock();

    //   let node1 = lockArr.nodes.find((item1) => item1.id == item.id);
    //   console.log(node1, "node1", node);

    //   let model = {
    //     id: node1.id,
    //     style: node1.style,
    //     // stateStyles: node1.stateStyles,
    //   };
    //   node.update(model);
    // });

    // for (let i = 0; i < arr.nodes.length; i++) {
    //   // 去掉解锁的节点
    //   for (let j = 0; j < lockArr.nodes.length; j++) {
    //     if (arr.nodes[i].id == lockArr.nodes[j].id) {
    //       lockArr.nodes.splice(j, 1);
    //       console.log(lockArr.nodes, arr.nodes);
    //       break;
    //     }
    //   }
    // }
    // useSelectGraphStore.setLockSelectCanvas(
    //   // 将锁定的节点存起来，解锁时需要原始节点的样式
    //   lockArr
    // );
  }
});

/**
 * 类案分析
 */
emitter.on("leianEvent", () => {
  let selectedNode = JSON.parse(
    JSON.stringify(useSelectGraphStore.getSelectCanvas())
  );
  if (!selectedNode) return ElMessage("请选择节点后操作");
  selectedNode.nodes = selectedNode.nodes.map((item) => {
    return {
      count: 100,
      vid: item.vid,
      tags: item.tags,
    };
  });
  console.log(selectedNode);
  similarAnalysis(selectedNode.nodes).then((res) => {
    console.log(res);
    if (!res.length) return ElMessage("暂无数据");
    let nodeArr = [];
    res.forEach((item) => {
      nodeArr = nodeArr.concat(
        item.similarAnalysis.map((it) => {
          it.id = it.vid;
          it.label = getSysName(it.tags);
          return it;
        })
      );
    });
    // console.log(nodeArr, "nodeArr");
    useCanvasStore.setCanvasData(nodeArr);
  });
});

// 搜索结果获取sysName值
const getSysName = (tags) => {
  let sysName = "";
  tags.forEach((item) => {
    if (item.properties.sys_name) {
      sysName = item.properties.sys_name;
    }
  });
  return sysName;
};

/**
 * 标注相关
 */
const dimensionDia = ref(false);
const ruleFormRef = ref(null);
const ruleForm = reactive({
  name: "",
  color: "rgba(75, 156, 244, 1)",
});

const rules = reactive({
  name: [
    {
      required: true,
      message: "请输入标注名称，最多20个字符",
      trigger: "blur",
      max: 20,
    },
  ],
  color: [{ required: true, message: "请选择", trigger: "blur" }],
});
emitter.on("dimensionEvent", (type) => {
  if (type == "add") {
    dimensionDia.value = true;
  } else {
    let selectedNode = useSelectGraphStore.getSelectCanvas();
    selectedNode.nodes.forEach((item) => {
      let node = graph.value.findById(item.id);
      let model = {
        id: item.id,
        dimensionCfg: {
          name: "",
          style: {
            fill: "#222",
            fontSize: 12,
          },
        },
      };
      graph.value.updateItem(node, model);
      // node.update(model);
    });
  }
});
/** 关闭添加标注弹窗 */
const handleClose = () => {
  console.log(ruleFormRef.value);
  ruleFormRef.value.resetFields();
};
/** 添加标注 */
const addDimension = () => {
  ruleFormRef.value.validate((valid, fields) => {
    if (valid) {
      let selectedNode = useSelectGraphStore.getSelectCanvas();
      selectedNode.nodes.forEach((item) => {
        let node = graph.value.findById(item.id);
        let model = {
          id: item.id,
          dimensionCfg: {
            name: ruleForm.name,
            style: {
              fill: ruleForm.color,
              fontSize: 12,
            },
          },
        };
        graph.value.updateItem(node, model);
        // node.update(model);
        // console.log(model,555);
      });

      dimensionDia.value = false;
    }
  });
};
/** 导入功能 */
emitter.on("handleImport", (importData) => {
  const data = {
    // 现在图中的所有节点
    nodes: graph.value.getNodes().map((item) => item.getModel()),
    edges: graph.value.getEdges().map((item) => item.getModel()),
  };
  data.nodes = uniqueFunc(data.nodes.concat(importData.nodes));
  data.edges = uniqueFunc(data.edges.concat(importData.edges));
  useCanvasStore.setCanvas(data);
  console.log(data, importData, uniqueFunc(data.nodes));
});

defineExpose({
  graph,
});
</script>

<template>
  <div class="canvasG6-main">
    <!--    画布-->
    <div id="mountNode" class="mountNode"></div>

    <!--    图钉-->
    <!-- <Affix></Affix> -->
    <div class="graph-toolbar-content" id="graph-toolbar-content"></div>

    <!--    左侧抽屉栏-->
    <DrawerLeft></DrawerLeft>

    <!--    右侧抽屉栏-->
    <DrawerRight></DrawerRight>

    <!--    关系拓展弹窗-->
    <relationDialog
      v-if="relationDialogShow"
      v-model:visible="relationDialogShow"
    ></relationDialog>

    <!-- 添加标注 -->
    <el-dialog
      v-model="dimensionDia"
      title="添加标注"
      width="570px"
      @close="handleClose"
    >
      <el-form
        ref="ruleFormRef"
        :model="ruleForm"
        :rules="rules"
        label-width="80px"
        class="demo-ruleForm"
      >
        <el-form-item label="标注名称" prop="name">
          <el-input v-model="ruleForm.name" placeholder="最多输入20个字符" />
        </el-form-item>
        <el-form-item label="标注颜色" prop="color">
          <el-color-picker v-model="ruleForm.color" show-alpha />
        </el-form-item>
      </el-form>
      <template #footer>
        <span class="dialog-footer">
          <el-button @click="dimensionDia = false">取消</el-button>
          <el-button type="primary" @click="addDimension"> 确定 </el-button>
        </span>
      </template>
    </el-dialog>
  </div>
</template>

<style lang="scss" scoped>
.canvasG6-main {
  position: relative;
  width: 100%;
  height: 100%;
  padding: 10px;
  background-color: #fff;

  .mountNode {
    width: 100%;
    height: 100%;
    background: url("@/assets/images/canvasbg.png");
  }

  .graph-toolbar-content {
    position: absolute;
    right: 16px;
    bottom: 24px;
  }
}
</style>

<style lang="scss">
.custom-menu-bar-association {
  padding: 8px 0;
  background: #fff;
  border: 1px solid #1010b5;
  box-shadow: 0 4px 16px 0 rgb(1 13 55 / 10%);
  opacity: 1;

  .line {
    width: 100%;
    height: 1px;
    background-color: #c7c9cf;
  }

  .disabel {
    color: #c7c9cf;
    pointer-events: none;
    cursor: not-allowed;
  }
}
</style>
